www.gusucode.com > 有监督的 CNN 网络完成对MNIST 数字的识别 > 有监督的 CNN 网络完成对MNIST 数字的识别/CNN—卷积神经网络数字识别/cnet_tool.m
function varargout = cnet_tool(varargin) % 更方便将MNIST数据文件中(t10k-images-idx3-ubyte、 % t10k-labels-idx1-ubyte train-images-idx3-ubyte % 和train-labels-idx1-ubyte)读取出来, % 所以演示可以自动找到他们。 % 2014-12-12 mInputArgs = varargin; % 变长度输入宗量,调用GUI(Graphical User Interface 图形用户界面)时命令行参数 mOutputArgs = {}; % 变量用于存储输出当GUI返回 mIconCData = []; % 用CData的图标编辑这个GUI的维度 % (mIconHeight,mIconWidth,3) mIsEditingIcon = false; % 标记显示当前鼠标移动是否用于编辑颜色 % 变量支持自定义属性/值配对 mPropertyDefs = {... % 支持自定义属性/值配对的GUI 'iconwidth', @localValidateInput, 'mIconWidth'; 'iconheight', @localValidateInput, 'mIconHeight'; 'MNISTfile', @localValidateInput, 'mMNISTFile'}; mIconWidth = 28; % 通过使用输入属性来初始化“iconwidth” mIconHeight = 28; % 通过使用输入属性来初始化“iconheight” % % mMNISTFile = './MNIST/t10k-images-idx3-ubyte'; %格式满足(根目录,'./'); % % Images = {0}; im_ptr = 1; autorecognition = false; tmp = load('cnet.mat'); cnet = tmp.sinet; % %在这个GUI上创建所有UI对象,这样可以在这个GUI用对应的函数 hMainFigure = figure(... 'Units','characters',... 'MenuBar','none',... 'Toolbar','none',... 'Position',[71.8 34.7 106 36.15],... 'WindowStyle', 'normal',... 'WindowButtonDownFcn', @hMainFigureWindowButtonDownFcn,... 'WindowButtonUpFcn', @hMainFigureWindowButtonUpFcn,... 'WindowButtonMotionFcn', @hMainFigureWindowButtonMotionFcn); hIconEditPanel = uipanel(... 'Parent',hMainFigure,... 'Units','characters',... 'Clipping','on',... 'Position',[1.8 4.3 68.2 27.77]); hIconEditAxes = axes(... 'Parent',hIconEditPanel,... 'vis','off',... 'Units','characters',... 'Position',[2 1.15 64 24.6]); hIconFileText = uicontrol(... 'Parent',hMainFigure,... 'Units','characters',... 'HorizontalAlignment','left',... 'Position',[3.8 32.9 16.2 1.46],... 'String','MNIST 文件夹: ',... 'Style','text'); hIconFileEdit = uicontrol(... 'Parent',hMainFigure,... 'Units','characters',... 'HorizontalAlignment','left',... 'Position',[19.8 32.9 78.2 1.62],... 'String','创建一个新的图标或键入一个图标图像文件进行编辑',... 'Enable','inactive',... 'Style','edit',... 'ButtondownFcn',@hIconFileEditButtondownFcn,... 'Callback',@hIconFileEditCallback); hIconFileButton = uicontrol(... 'Parent',hMainFigure,... 'Units','characters',... 'Callback',@hIconFileButtonCallback,... 'Position',[98 32.85 5.8 1.77],... 'String','...',... 'TooltipString','Import From Image File'); hPreviewPanel = uipanel(... 'Parent',hMainFigure,... 'Units','characters',... 'Title','预览',... 'Clipping','on',... 'Position',[71.8 19.15 32.2 13]); hPreviewControl = uicontrol(... 'Parent',hPreviewPanel,... 'Units','characters',... 'Enable','inactive',... 'Visible','off',... 'Position',[2 3.77 16.2 5.46],... 'String',''); hPrevDigitButton = uicontrol(... 'Parent',hMainFigure,... 'Units','characters',... 'Position',[80 20 5 2],... 'String','<',... 'Callback',@hPrevDigitButtonCallback); hNextDigitButton = uicontrol(... 'Parent',hMainFigure,... 'Units','characters',... 'Position',[91.7 20 5 2],... 'String','>',... 'Callback',@hNextDigitButtonCallback); hAutorecognitionCheck = uicontrol(... 'Parent', hMainFigure,... 'Units', 'characters',... 'HorizontalAlignment', 'left',... 'Position', [71.8 17.6 32.2 1],... 'String','自动识别',... 'Style','CheckBox', ... 'Callback',@hAutorecognitionCheckCallback, ... 'Value', 0); hResultPanel = uipanel(... 'Parent',hMainFigure,... 'Units','characters',... 'Title','识别结果显示',... 'Clipping','on',... 'Position',[71.8 4.3 32.2 13]); hResultText = uicontrol(... 'Parent',hResultPanel,... 'Units','normalized',... 'Style','text', ... 'Enable','inactive',... 'Visible','on',... 'FontSize', 50, ... 'Position',[.2 .2 .6 .6],... 'String',''); for i = 0:9, hResultDigits(1+i) = uicontrol(... 'Parent',hResultPanel,... 'Units','normalized',... 'Enable','inactive',... 'Style','text', ... 'FontSize', 14, ... 'Position',[.02+i*.095 .05 .09 .128],... 'String', char('0'+i), ... 'ForegroundColor', [1 1 1]); end hSectionLine = uipanel(... 'Parent',hMainFigure,... 'Units','characters',... 'HighlightColor',[0 0 0],... 'BorderType','line',... 'Title','',... 'Clipping','on',... 'Position',[2 3.62 102.4 0.077]); hOKButton = uicontrol(... 'Parent',hMainFigure,... 'Units','characters',... 'Position',[65.8 0.62 17.8 2.38],... 'String','确定',... 'Callback',@hOKButtonCallback); hCancelButton = uicontrol(... 'Parent',hMainFigure,... 'Units','characters',... 'Position',[85.8 0.62 17.8 2.38],... 'String','取消',... 'Callback',@hCancelButtonCallback); hRecognizeButton = uicontrol(... 'Parent',hMainFigure,... 'Units','characters',... 'Position',[10.0 0.62 17.8 2.38],... 'String','识别',... 'Callback',@hRecognizeButtonCallback); hClearButton = uicontrol(... 'Parent',hMainFigure,... 'Units','characters',... 'Position',[30.0 0.62 17.8 2.38],... 'String','清除',... 'Callback',@hClearButtonCallback); % host ColorPalette PaletteContainer和保持功能,处理让其选择颜色编辑图标 % 改变所需的合适的外观和运行在不同的平台上 prepareLayout(hMainFigure); % 当调用GUI时提供处理输入参数的命令行 processUserInputs(); % 初始化iconEditor,使用默认或自定义的数据通过属性/值对 localUpdateIconPlot(); % 使GUI出现在屏幕上 set(hMainFigure,'visible', 'on'); movegui(hMainFigure,'onscreen'); % 使GUI阻塞(blocking) uiwait(hMainFigure); % 如果请求,返回编辑图标CData mOutputArgs{1} =mIconCData; if nargout>0 [varargout{1:nargout}] = mOutputArgs{:}; end %------------------------------------------------------------------ function hMainFigureWindowButtonDownFcn(hObject, eventdata) %鼠标在图上被按下时调用。 %用来改变特定的图标的颜色数据点下鼠标的当前选中colorPalette的颜色 if (ancestor(gco,'axes') == hIconEditAxes) mIsEditingIcon = true; localEditColor(); end end %------------------------------------------------------------------ function hMainFigureWindowButtonUpFcn(hObject, eventdata) % 释放窗口当鼠标点击退出编辑模式的图标 mIsEditingIcon = false; end %------------------------------------------------------------------ function hMainFigureWindowButtonMotionFcn(hObject, eventdata) %回调时调用鼠标移动,这样可以更新图标颜色数据的编辑模式 if (ancestor(gco,'axes') == hIconEditAxes) localEditColor(); end end %------------------------------------------------------------------ function hIconFileEditCallback(hObject, eventdata) % %的回调时调用用户改变了图标文件名称的图标可以加载 file = get(hObject,'String'); if exist(file, 'file') ~= 2 errordlg(['The given icon file cannot be found ' 10, file], ... 'Invalid Icon File', 'modal'); set(hObject, 'String', mMNISTFile); else mIconCData = []; localUpdateIconPlot(); end end %------------------------------------------------------------------ function hIconFileEditButtondownFcn(hObject, eventdata) %调称用户第一次按下鼠标的editbox图标文件 set(hObject,'String',''); set(hObject,'Enable','on'); set(hObject,'ButtonDownFcn',[]); uicontrol(hObject); end %------------------------------------------------------------------ function hOKButtonCallback(hObject, eventdata) % OK按钮被按下时调用 uiresume; delete(hMainFigure); end %------------------------------------------------------------------ function hCancelButtonCallback(hObject, eventdata) % 取消按钮被按下时调用 mIconCData =[]; uiresume; delete(hMainFigure); end %------------------------------------------------------------------ function hRecognizeButtonCallback(hObject, eventdata) Ip = preproc_image(mIconCData); [out cnet] = sim(cnet, Ip); max_out = max(out); for out_i = 1:numel(out), set(hResultDigits(out_i), 'ForegroundColor', [1 1 1]*(1.8-out(out_i))/3.6) end digit = find(out == max_out, 1) - 1; if ~isempty(digit), set(hResultText, 'string', char('0'+digit), 'ForegroundColor', [1 1 1]*(1.8-max_out)/3.6) end end %------------------------------------------------------------------ function hClearButtonCallback(hObject, eventdata) mIconCData = ones(mIconHeight, mIconWidth, 3); localUpdateIconPlot(); if autorecognition, hRecognizeButtonCallback(hObject, eventdata) end end %------------------------------------------------------------------ function hAutorecognitionCheckCallback(hObject, eventdata) autorecognition = get(hAutorecognitionCheck, 'Value'); if autorecognition, hRecognizeButtonCallback(hObject, eventdata) end end %------------------------------------------------------------------ function hIconFileButtonCallback(hObject, eventdata) %回调时调用的图标文件选择按钮被按下 filespec = {'*.*', 'Database file '}; [filename, pathname] = uigetfile(filespec, 'Pick an database file', mMNISTFile); if ~isequal(filename,0) mMNISTFile = fullfile(pathname, filename); set(hIconFileEdit, 'ButtonDownFcn',[]); set(hIconFileEdit, 'Enable','on'); mIconCData = []; localUpdateIconPlot(); elseif isempty(mIconCData) set(hPreviewControl,'Visible', 'off'); end end function hPrevDigitButtonCallback(hObject, eventdata) if(im_ptr>1) im_ptr=im_ptr-1; end im = abs(double(Images{im_ptr})/255-1)'; mIconCData = cat(3,im,im,im); localUpdateIconPlot(); if autorecognition, hRecognizeButtonCallback(hObject, eventdata) end end function hNextDigitButtonCallback(hObject, eventdata) if(im_ptr<numel(Images)) im_ptr=im_ptr+1; end im = abs(double(Images{im_ptr})/255-1)'; mIconCData = cat(3,im,im,im); localUpdateIconPlot(); if autorecognition, hRecognizeButtonCallback(hObject, eventdata) end end %------------------------------------------------------------------ function localEditColor % helper函数改变一个图标的颜色数据点在colorPalette当前选中的颜色 if mIsEditingIcon pt = get(hIconEditAxes,'currentpoint'); x = max(1, min(ceil(pt(1,1)), mIconWidth)); y = max(1, min(ceil(pt(1,2)), mIconHeight)); % 更新颜色选择 m = get(gcf,'SelectionType'); if m(1) == 'n', % 左按钮按下 mIconCData(y, x,:) = 0; if y<mIconHeight, mIconCData(y+1,x,:) = .8*mIconCData(y+1,x,:); end if x<mIconWidth, mIconCData(y,x+1,:) = .8*mIconCData(y,x+1,:); end if y>1, mIconCData(y-1,x,:) = .8*mIconCData(y-1,x,:); end if x>1, mIconCData(y,x-1,:) = .8*mIconCData(y,x-1,:); end else mIconCData(y, x,:) = 1; end localUpdateIconPlot(); end end %------------------------------------------------------------------ function localUpdateIconPlot % 时更新iconEditor helper函数图标数据更改 % 初始化图标CData如果没有初始化 if isempty(mIconCData) if exist(mMNISTFile, 'file') == 2 try Images = readMNIST_image(mMNISTFile,1000); %im_ptr = 1; im = abs(double(Images{im_ptr})/255-1)'; mIconCData = cat(3,im,im,im); set(hIconFileEdit, 'String', mMNISTFile); catch errordlg(['Could not load MNIST database file successfully. ',... 'Make sure the file name is correct: ' mMNISTFile],... 'Invalid MNIST File', 'modal'); mIconCData = nan(mIconHeight, mIconWidth, 3); end else mIconCData = nan(mIconHeight, mIconWidth, 3); end end % 更新预览控件 rows = size(mIconCData, 1); cols = size(mIconCData, 2); previewSize = getpixelposition(hPreviewPanel); % 标题 previewSize(4) = previewSize(4) -15; controlWidth = previewSize(3); controlHeight = previewSize(4); controlMargin = 6; if rows+controlMargin<controlHeight controlHeight = rows+controlMargin; end if cols+controlMargin<controlWidth controlWidth = cols+controlMargin; end setpixelposition(hPreviewControl,[(previewSize(3)-controlWidth)/2,(previewSize(4)-controlHeight)/2, controlWidth, controlHeight]); set(hPreviewControl,'CData', mIconCData,'Visible','on'); % 更新 图标编辑窗格 set(hIconEditPanel, 'Title',['图标编辑窗格 (', num2str(rows),' X ', num2str(cols),')']); s = findobj(hIconEditPanel,'type','surface'); if isempty(s) gridColor = get(0, 'defaultuicontrolbackgroundcolor') - 0.2; gridColor(gridColor<0)=0; s=surface('edgecolor',gridColor,'parent',hIconEditAxes); end % 设置xdata、ydata zdata以防行和/或关口的变化 set(s,'xdata',0:cols,'ydata',0:rows,'zdata',zeros(rows+1,cols+1),'cdata',localGetIconCDataWithNaNs()); set(hIconEditAxes,'drawmode','fast','xlim',[-.5 cols+.5],'ylim',[-.5 rows+.5]); axis(hIconEditAxes, 'ij', 'off'); end %------------------------------------------------------------------ function cdwithnan = localGetIconCDataWithNaNs() % 增加非数值(NaN)的边缘mIconCData将整个图标呈现在图窗格中。这是必要的,因为表面的行为。 cdwithnan = mIconCData; cdwithnan(:,end+1,:) = NaN; cdwithnan(end+1,:,:) = NaN; end %------------------------------------------------------------------ function processUserInputs % helper函数,处理输入属性/值对 % 应用可能的图和可辨认的自定义属性/值对 for index=1:2:length(mInputArgs) if length(mInputArgs) < index+1 break; end match = find(ismember({mPropertyDefs{:,1}},mInputArgs{index})); if ~isempty(match) % 验证输入,并将其分配给一个变量 if ~isempty(mPropertyDefs{match,3}) && mPropertyDefs{match,2}(mPropertyDefs{match,1}, mInputArgs{index+1}) assignin('caller', mPropertyDefs{match,3}, mInputArgs{index+1}) end else try set(topContainer, mInputArgs{index}, mInputArgs{index+1}); catch % 如果这不是一个有效的图属性值对,让两个去到下一个 continue; end end end end %------------------------------------------------------------------ function isValid = localValidateInput(property, value) % helper函数来验证用户提供输入属性/值对。你可以在这里选择显示警告或错误。 isValid = false; switch lower(property) case {'iconwidth', 'iconheight'} if isnumeric(value) && value >0 isValid = true; end case 'MNISTfile' if exist(value,'file')==2 isValid = true; end end end end % iconEditor结束 %------------------------------------------------------------------ function prepareLayout(topContainer) %这个效用函数负责相关问题的外观和运行在多个平台上。 %可以重用该函数在其他gui或修改它以适合你的需要。 allObjects = findall(topContainer); warning off %临时报告修复 try titles=get(allObjects(isprop(allObjects,'TitleHandle')), 'TitleHandle'); allObjects(ismember(allObjects,[titles{:}])) = []; catch end warning on % 使用这个GUI文件的名称作为标题的数字 defaultColor = get(0, 'defaultuicontrolbackgroundcolor'); if isa(handle(topContainer),'figure') set(topContainer,'Name', mfilename, 'NumberTitle','off'); % 使GUI对象的图颜色匹配 set(topContainer, 'Color',defaultColor); end % 使GUI对象可用于回调,这样他们不能改变意外其他MATLAB命令 set(allObjects(isprop(allObjects,'HandleVisibility')), 'HandleVisibility', 'Callback'); % 使GUI的正常运行在多个平台上使用合适的单位 if strcmpi(get(topContainer, 'Resize'),'on') set(allObjects(isprop(allObjects,'Units')),'Units','Normalized'); else set(allObjects(isprop(allObjects,'Units')),'Units','Characters'); end %你可能想要修改editbox,popupmenu上默认的颜色,在Windows上列表框白色 if ispc candidates = [findobj(allObjects, 'Style','Popupmenu'),... findobj(allObjects, 'Style','Edit'),... findobj(allObjects, 'Style','Listbox')]; set(findobj(candidates,'BackgroundColor', defaultColor), 'BackgroundColor','white'); end end function out = preproc_image(id) %图像预处理 Inorm = id(:,:,1); Inorm(~isfinite(Inorm)) = 1; Inorm = abs(Inorm-1)'; out = zeros(32); out(3:30,3:30) = Inorm; if sum(out(:))>0, gain = 1./ std(out(:)); out = (out - mean(out(:))).*gain; end end function I = readMNIST_image(filepath,num) %读MNIST_image MNIST handwriten阅读图像数据库。读取只有图片没有标签,指定文件名 % %的语法 % % I = readMNIST_image(filepath num) % %的描述 %的输入: % filepath——名称数据库文件的路径 % n -图像处理的数量 %输出: % I - 28 x28训练图像大小的单元阵列 % = = = = = = = = = = =加载训练集 fid = fopen(filepath,'r','b'); %大端法(二进位资料次序) magicNum = fread(fid,1,'int32'); %幻数 if(magicNum~=2051) display('Error: cant find magic number'); return; end imgNum = fread(fid,1,'int32'); %图片的数量 rowSz = fread(fid,1,'int32'); %图片的高度 colSz = fread(fid,1,'int32'); %图片的宽度 if(num<imgNum) imgNum=num; end for k=1:imgNum I{k} = uint8(fread(fid,[rowSz colSz],'uchar')); end fclose(fid); end